/***************************************************************************
                          gui_base.c  -  description
                             -------------------
    begin                : 2012-04-13
    copyright            : (C) 2012 by CADCAM-Services Franz Reiter
    email                : franz.reiter@cadcam.co.at

****************************************************************************

Independant GraficalUserInterface-functions.
Independant from Gtk. Gtk-functions see ../gui_gtk/.


TODO:


-----------------------------------------------------
Modifications:
2012-04-13 First version; extracted from Gtk-toolbox. RF.

-----------------------------------------------------
*/
#ifdef globTag
void GUI(){}
#endif
/*!
\file ../gui/gui_base.c
\ingroup grp_ut_gui
\code

------ Links to Gtk ---------------
../gui_gtk/gtk_base.c              Window Box
../gui_gtk/gtk_label.c             Label
../gui_gtk/gtk_button.c            Button (with image) Checkbox
../gui_gtk/gtk_menu.c              Menu
../gui_gtk/gtk_entry.c             Entry
../gui_gtk/gtk_image.c             Image
../gui_gtk/gtk_dlg_std.c           Messagebox Dialogbox Slider Colorselect
../gui_gtk/gtk_dlg_files.c         File open / save
../gui_gtk/gtk_msgWin.c            Messagewindow
../gui_gtk/gtk_lists.c             List
../gui_gtk/gtk_container.c         Frame Toolbar Notebook Paned
../gui_gtk/gtk_multichoice.c       Radiobuttons Popup-menu Option-menu
../gui_gtk/gtk_tree_it.c           Treeview with icon + text
../gui_gtk/gtk_opengl.c            OpenGL-window
../gtk_gl_x11.c                    Gtk-binding OpenGL


=====================================================
Liste_Funktionen_Beginn:

GUI_obj_init             get a new memBlockId <UI_umbId>
GUI_obj_save             save UI_tmpSpc -> memoryblock <UI_umbId>
GUI_obj_clear            clear the local memSpc UI_tmpSpc
GUI_obj_spc              get address & memspc for new widget (in UI_tmpSpc)
GUI_obj_tmp              get temporary object; only one possible.
GUI_obj_pos              get widget-data-position from MemObj
GUI_obj_src              get widget-nr from MemObj
GUI_obj_cmp              compare 2 MemObj's                         INLINE
GUI_obj_free             free the memBlock

GUI_obj_parentBox        get widget-type & data data from MemObj; check for Box.
GUI_obj_typ              get widget-type & widget-data from MemObj
GUI_obj_destroy          free memBlock from MemObj
GUI_obj_dump_o

Liste_Funktionen_Ende:
=====================================================

\endcode *//*----------------------------------------

UI_tmpSpc is a permanent active memoryspace.
All widget-objects for the active window are stored in UI_tmpSpc.
If a new window is started before the active window is destroyed, then
  UI_tmpSpc is saved in a memoryblock (by malloc new space, copy to new space).
If a saved window gets destroyed, its memoryblock is freed.



=====================================================
compile mit gcc:
cc -c -O0 -g3 -Wall gui_base.c

Windows:
cl -c gui_base.c




test offline:
cc gui_base.c ut_umb.c ut_umem.c ut_mainut.c -DOFFLINE_GUI1 -lm&&./a.out
ctags -f gui_base.tag gui_base.c

*/


// #include "../xa/MS_Def0.h"

#include <stdio.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>                     // memcpy

#include "../ut/ut_umem.h"              // Memspc
#include "../ut/ut_umb.h"               // UMB
#include "../gui/gui_types.h"           // TYP_GUI_Win
#include "../gui/gui_base.h"


// ../ut/ut_geo.h
#define Typ_Error          0  ///<     U0 = undefined


#define TMPSPC_SIZ   5000
#define TMPSPC_INC   5000


//----------------------------------------------------------------
// was ../gtk/ut_gtk.c: 
int       UI_fontsizX, UI_fontsizY;
// was ../xa/xa_ui.c
void      *UI_MainWin;
void      *UI_act_wi;


//----------------------------------------------------------------
// local:
static Memspc UI_tmpSpc=UME_NEW;
static void   *UI_tmpPos = NULL;
static int    UI_umbId;                // userMemoryBlockNr;
static int    UI_srcId;                // widget-Nr;




//================================================================
  void GUI_obj_destroy (void *wo) {
//================================================================
/// free memBlock from MemObj

  MemObj  *mo;


  mo = &((Obj_Unknown*)wo)->mem_obj;

  printf("GUI_obj_destroy %d\n",mo->mbID);


  // is winMem == tmpSpc (local):
  if(mo->mbID == UI_umbId) {
    // yes: clear temSpc
    GUI_obj_clear ();
  }

  GUI_obj_free (mo);   // free memBlock / set memBlock-stat = 0

}


//================================================================
  void* GUI_obj_parentBox (void *o_par) {
//================================================================
/// get widget-type & data from MemObj; check for Box.


  int   pTyp;
  void  *g_par, *w_par;


  // get widget-type & widget-data from MemObj
  GUI_obj_typ (&pTyp, (void**)&g_par, o_par);
  if(!pTyp) return (NULL);


  if((pTyp == TYP_GUI_BoxH) ||
     (pTyp == TYP_GUI_BoxV) ||
     (pTyp == TYP_GUI_Win))    {
    w_par = ((Obj_Box*)g_par)->box;
      printf(" w_par = %p\n",w_par);

  } else {
    printf("***** GUI_obj_parentBox parent must be box, not %d\n",pTyp);
    return NULL;
  }

  return (w_par);

}


//================================================================
  void GUI_obj_typ (int *pTyp, void **g_par, void *o_par) {
//================================================================
/// get widget-type & widget-data from MemObj


  // get widget-data from MemObj
  *g_par = GUI_obj_pos (o_par);
  if(!g_par) {
    *pTyp = Typ_Error;
    printf("***** GUI_obj_typ E001\n");
    return;
  }

  // get widget-type
  *pTyp = ((Obj_Unknown*)*g_par)->gio_typ;

  printf("ex GUI_obj_typ %d\n",*pTyp);


}


//================================================================
  int GUI_obj_init () {
//================================================================
/// \code
/// get a new memBlockId <UI_umbId>
/// init local memSpc UI_tmpSpc
/// \endcode


  int   irc=0;
  void  *oPos;


  printf("GUI_obj_init \n");


  // get tempSpace ..
  if(!UI_tmpPos) {
    // init local UI_tmpSpc
    UME_malloc (&UI_tmpSpc, TMPSPC_SIZ, TMPSPC_INC);
    UI_tmpPos = UME_get_start (&UI_tmpSpc);
      printf(" UI_tmpPos = %p\n",UI_tmpPos);
    goto L_getNew;
  }


  // test if UI_tmpSpc ( = local space for widgets is empty)
  if(UME_get_start(&UI_tmpSpc) == UME_get_next(&UI_tmpSpc)) {
      printf(" winMem is empty\n");
    // must increment the blockId for this reUse
    irc = UME_reuse (UI_umbId);
    goto L_exit;
  }

    printf(" winMem is NOT empty\n");

  // save UI_tmpSpc -> memoryblock <UI_umbId>
  irc = UME_obj_save (UI_umbId, &UI_tmpSpc);
  if(irc < 0) return irc;

  // clear UI_tmpSpc
  GUI_obj_clear ();


  L_getNew:
  // get a new memBlock-index and Id
  UI_umbId = UMB_reserve__ (&irc);


  L_exit:
    // reset widget-nr
    UI_srcId = 0;

    // first object in memSpc is the nr of records;
    UME_obj_reserve (&oPos,  &UI_tmpSpc, sizeof(int), UI_umbId);
    memcpy (oPos, &irc, sizeof(int));

      printf("ex GUI_obj_init ind=%d id=%d\n",UI_umbId,irc);

    return irc;      // returns Id

}


//================================================================
  int GUI_obj_save () {
//================================================================
/// \code
/// save UI_tmpSpc -> memoryblock <UI_umbId>
///   & clear UI_tmpSpc
///   & get new memBlockId
/// \endcode

  int   irc;


  printf("GUI_obj_save %d\n",UI_umbId);

  // save UI_tmpSpc -> memoryblock <UI_umbId>
  irc = UME_obj_save (UI_umbId, &UI_tmpSpc);
  if(irc < 0) return irc;

  // clear UI_tmpSpc
  GUI_obj_clear ();

  // get new memBlockId <UI_umbId>
  GUI_obj_init ();

  return 0;

}


//================================================================
  void GUI_obj_clear () {
//================================================================
/// clear the local memSpc UI_tmpSpc

  printf("CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC \n");
  printf("GUI_obj_clear \n");


  UME_set_free (-1, &UI_tmpSpc);

}


//================================================================
  MemObj GUI_obj_tmp (void **oPos, int siz) {
//================================================================
/// get temporary object; only one possible.

  MemObj    mo;


  mo.mbID = UI_umbId;
  mo.ioff = UI_tmpSpc.next - UI_tmpSpc.start;

  if(mo.ioff < 4) {
    // 0 = invalid adress !
    UI_tmpSpc.next = UI_tmpSpc.start + 4;
    mo.ioff = 4;
  }

  *oPos = UI_tmpSpc.next;

  // copy MemObj into reserved space 
  ((Obj_Unknown*)*oPos)->mem_obj = mo;


  return (mo);

}


//================================================================
  MemObj GUI_obj_spc (void **oPos, int siz) {
//================================================================
/// \code
/// get address & memspc for new widget (in UI_tmpSpc)
/// Input:
///   siz        size for new widget
/// Output:
///   *oPos      free space for the new object (in UI_tmpSpc)
///   RetCod     memblockId (reserved) and dataOffset
/// \endcode

  MemObj    mo;


  printf("GUI_obj_spc siz=%d UI_umbId=%d\n",siz,UI_umbId);

  // get <siz> bytes in UI_tmpSpc and set memBlock-Id & memBlock-offset
  mo = UME_obj_reserve (oPos,  &UI_tmpSpc, siz, UI_umbId);
  if(mo.mbID < 0) return (mo);

  // copy MemObj into reserved space 
  ((Obj_Unknown*)*oPos)->mem_obj = mo;

  // save gui-sourcename gio_src
  ((Obj_Unknown*)*oPos)->gio_src = UI_srcId;

  // increment gui-sourcename
  ++UI_srcId;

  return (mo);
}


//================================================================
  void GUI_obj_dump__ () {
//================================================================

  int   ioff;
  void  *pos;


  ioff = 0;
  pos  = UI_tmpPos;


  printf("-------------- GUI_obj_dump__ --------- UI_umbId=%d UI_tmpPos=%p\n",
     UI_umbId, UI_tmpPos);

}


//================================================================
  void GUI_obj_dump_mo (MemObj *mo) {
//================================================================
/// dump MemObj

  printf("-------------- GUI_obj_dump_mo -------------- mbID=%d ioff=%d\n",
     mo->mbID, mo->ioff);

}



//================================================================
  void GUI_obj_dump_o (void *go) {
//================================================================
/// dump gui-object

  MemObj  *mo;


  if(!go) {
    printf("-------------- GUI_obj_dump_o -------------- INVALID OBJ\n");
    return;
  }

  mo = &((Obj_Unknown*)go)->mem_obj;

  printf("-------------- GUI_obj_dump_o -------------- mbID=%d ioff=%d\n",
      mo->mbID, mo->ioff);
    printf(" typ=%d stat=%d\n",
      ((Obj_Unknown*)go)->gio_typ,
      ((Obj_Unknown*)go)->gio_src);

    // printf(" data=|%s|\n",go->data);
    // printf(" func=|%p|\n",go->uFunc);



}


//================================================================
  int GUI_obj_src (MemObj *mo) {
//================================================================
/// GUI_obj_src              get widget-nr from MemObj


  Obj_Unknown *go;

  go = GUI_obj_pos (mo);
  if(!go) return 0;

  return (go->gio_src);

}


//================================================================
  void* GUI_obj_pos (MemObj *mo) {
//================================================================
/// \code
/// get widget-data-position from MemObj
/// MemObj contains window-nr and offset in the window-memoryblock.
/// widget-data contains at least Obj_Unknown
///
/// Example:
/// Obj_Unknown *go;
/// go = GUI_obj_pos (mo);
/// printf(" typ=%d src=%d\n", go->gio_typ, go->gio_src);
/// \endcode


  // printf("GUI_obj_pos UI_umbId=%d\n",UI_umbId);


  if(!mo) {
    printf("***** GUI_obj_pos - MemObj = NULL\n");
    return NULL;
  }


  if(mo->ioff == 0) {
    printf("***** GUI_obj_pos - invalid MemObj\n");
    return NULL;
  }

  // get baseAdress of memSpc for Window <winID>
  if(UI_umbId == mo->mbID) {
      // printf(" _obj_pos local\n");
    return (UI_tmpPos + mo->ioff);

  } else {
      // printf(" _obj_pos extern\n");
    return (UME_obj_get (mo));
  }

}


//================================================================
  int GUI_obj_free (MemObj *mo) {
//================================================================
/// free the memBlock

  printf("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n");
  printf("GUI_obj_free %d\n",mo->mbID);

  return UMB_free (mo->mbID);

}




//========================================================
//========================================================
#ifdef OFFLINE_GUI1


typedef struct {double d1, d2; } myObj1;


//============================
  int main (int paranz, char *params[]) {
//============================

  int     mbId1, mbId2, ii1;
  myObj1  *o1, *o2;
  char    s1[256], *p1;
  Memspc  mSpc;
  MemObj  mo1, mo2;
  long    mSiz;
  void    *mPos;



  printf("OFFLINE ut_umb \n");


  // get memBlockId
  GUI_obj_init ();
  UMB_dump__ ();


  // get space for obj in memblock
  mo1 = GUI_obj_spc ((void*)&o1, sizeof(myObj1));


  // fill obj
  o1->d1 = 12.34;
  o1->d2 = 56.78;


  // get obj (yet out of tempSpc)
  o2 = GUI_obj_pos (&mo1);
  if(!o2) return 0;
  printf(" o2.d1=%lf\n",o2->d1);



  // get another memBlockId
  mbId2 = UMB_reserve__ (&ii1);
  UMB_dump__ ();


  // save tempSpace persistant -> memBlock & clear the tempSpace
  // OR GUI_obj_clear
  GUI_obj_save ();
  // GUI_obj_clear ();
  UMB_dump__ ();


  // get obj (now from memBlock)
  o2 = GUI_obj_pos (&mo1);
  if(!go) return 0;
  printf(" o2.d1=%lf\n",o2->d1);


  // clear the memBlock
  GUI_obj_free (&mo1);


  return 0;

}

#endif


// EOF
